/**
INFO:
	to get the Background from some picture
Author:
	Mark on 2014/4/10
	<mark199312@gmail.com>
*/


#include"Background.h"
#include<iostream>
using namespace std;

Background::Background()
{
	
}

Background::~Background()
{

}

Mat Background::getBM()
{
	return this->bM;
}

/**
init the bMT the two demension arrays
*/

void Background::initbMB()
{
	logInfo("start to init the bMB");
	this->bW=this->bMT[0].size().width;
	this->bH=this->bMT[0].size().height;

	int ar=this->bMT[0].size().area();

	//this->bMB=(bool **)malloc(sizeof(bool *)*h);
	this->bMB=new bool*[bH];

	this->bMB[0]=new bool[ar];

	int i=0;
	for(int i=1;i<bH;i++)
	{
		this->bMB[i]=this->bMB[i-1]+bW;
	}

	memset(this->bMB[0],0,ar);
}

void Background::setBM(Mat bM)
{
	this->bM=bM;
	initbMB();
}

/**
keep the bMT in some fixed num
and add the picture to bMT
*/

void Background::addBMT(Mat bMT)
{
	if(this->bMT.size()>BMTNUM)
	{
		this->bMT.pop_back();
	}

	this->bMT.insert(this->bMT.begin(),bMT);
}

bool Background::inMarginOfError(int a,int b,int marginError)
{
	//logInfo("process in MarginError");
	if(abs(a-b)<marginError)
	{
		return true;
	}

	return false;
}

/**
to get the specific background
*/

void Background::getSameAverage(Mat m,Mat n)
{
	logInfo("start to getSameAverage");
	int w=m.size().width;
	int h=m.size().height;

	//update the bool bmb and update the BM

	for(int i=0;i<h;i++)
	{
		for(int j=0;j<w;j++)
		{

			if(!bMB[i][j])
			{
				if(inMarginOfError(n.at<Vec3b>(i,j)[0],m.at<Vec3b>(i,j)[0]) && inMarginOfError(n.at<Vec3b>(i,j)[1],m.at<Vec3b>(i,j)[1]) && inMarginOfError(n.at<Vec3b>(i,j)[2],m.at<Vec3b>(i,j)[2]))
				{
					bMB[i][j]=1;
				}

				this->bM.at<Vec3b>(i,j)[0]=(n.at<Vec3b>(i,j)[0]+m.at<Vec3b>(i,j)[0])/2;
				this->bM.at<Vec3b>(i,j)[1]=(n.at<Vec3b>(i,j)[1]+m.at<Vec3b>(i,j)[1])/2;
				this->bM.at<Vec3b>(i,j)[2]=(n.at<Vec3b>(i,j)[2]+m.at<Vec3b>(i,j)[2])/2;
			}
		}
	}
}

/**
put all BMT to 
*/
void Background::getBackFromBMT()
{
	logInfo("start to getBackFromBMT");

	this->setBM(this->bMT[3]);
	/**
	this should notice
	when comparing the two pictures:
						must not same
						in end and start
	*/
	for(int i=0;i<=bMT.size()/2-1;i++)
	{
		this->getSameAverage(bMT[i],bMT[bMT.size()-i-1]);
	}
}

/**
get all background from pic
*/
void Background::cutBackground()
{
	logInfo("start to cutBackgroud from picture");

	for(int i=0;i<this->bM.size().height;i++)
	{
		for(int j=0;j<this->bM.size().width;j++)
		{
			if(this->bMB[i][j])
			{
				this->bM.at<Vec3b>(i,j)[0]=255;
				this->bM.at<Vec3b>(i,j)[1]=255;
				this->bM.at<Vec3b>(i,j)[2]=255;
			}
			else
			{
				this->bM.at<Vec3b>(i,j)[0]=0;
				this->bM.at<Vec3b>(i,j)[1]=0;
				this->bM.at<Vec3b>(i,j)[2]=0;
			}
		}
	}
}


/**
next is to process the Background to denoising
*/
void Background::denoising(int N,int M)
{
	string s="start to denoising ";
	s.push_back('0'+N);
	s.push_back(',');
	s.push_back('0'+M);

	logInfo(s.c_str());

	for(int i=0;i<this->bM.size().height;i++)
	{
		for(int j=0;j<this->bM.size().width-6;j++)
		{
			if(!this->bMB[i][j])
			{
				int sum=0;

				for(int k=j;k<N+j;k++)
				{
					if(!this->bMB[i][k])
					{
						sum++;
					}
				}
				if(sum>=M)
				{
					for(int k=j;k<N+j;k++)
					{
						this->bMB[i][k]=0;
					}
				}
				j+=(N-M);
			}
		}
	}



	for(int i=0;i<this->bM.size().width;i++)
	{
		for(int j=0;j<this->bM.size().height-6;j++)
		{
			if(!this->bMB[j][i])
			{
				int sum=0;

				for(int k=j;k<N+j;k++)
				{
					if(!this->bMB[k][i])
					{
						sum++;
					}
				}

				if(sum>=M)
				{
					for(int k=j;k<N+j;k++)
					{
						this->bMB[k][i]=0;
					}
				}

				j+=(N-M);
			}
		}
	}
}

/**
count the number of Background pixels
*/
int Background::countBMB()
{
	logInfo("start to countBMB");

	int sum=0;
	for(int i=0;i<this->bM.size().height;i++)
	{
		for(int j=0;j<this->bM.size().width;j++)
		{
			if(this->bMB[i][j])
			{
				sum++;
			}
		}
	}

	cout<<sum<<endl;
	return sum;
}

void Background::display()
{
	namedWindow("Background", WINDOW_NORMAL);
	imshow( "Background",this->bM); 
}

/**
being a thread to process the picture to get the background
*/

void Background::run()
{

}